home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The CICA Windows Explosion!
/
The CICA Windows Explosion! - Disc 2.iso
/
programr
/
tkern10.zip
/
SRC\IO.C
< prev
next >
Wrap
Text File
|
1994-07-10
|
11KB
|
520 lines
/*
* This file forms part of "TKERN" - "Troy's Kernel for Windows".
*
* Copyright (C) 1994 Troy Rollo <troy@cbme.unsw.EDU.AU>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This module takes care of tkern file operations. Most of these
* get passed on to tkfmangr so that files can be inherited by
* child processes in tkern.
*/
#include <windows.h>
#include <toolhelp.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <alloc.h>
#include <stdarg.h>
#include <errno.h>
#include <ctype.h>
#include <dir.h>
#include <sys/tfile.h>
#include <sys/task.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/tkern.h>
struct tfile _files[TNFILE];
static HGLOBAL hTFMem = 0;
struct tfunc *ptf = 0;
static int
find_location( struct task *pt,
int *fd,
int *ifd)
{
for (*ifd = 0; *ifd < TNFILE; (*ifd)++)
{
if (!_files[*ifd].tf_cnt)
break;
}
if (*ifd == TNFILE)
{
pt->nError = EMFILE;
return -1;
}
for (*fd = 0; *fd < UFILE_MAX; (*fd)++)
{
if (pt->files[*fd] == -1)
break;
}
if (*fd == UFILE_MAX)
{
pt->nError = EMFILE;
return -1;
}
return 0;
}
int far _export
tkern_open( char const *pchFile,
int nMode,
int nAccess)
{
int iDevice;
int id;
int fd;
int ifd;
char const *c;
struct task *pt;
BOOL bFile;
pt = GetTaskInfo();
ptf->iTask = (pt - _tasks);
if (!strncmp(pchFile, "\\dev\\", 5) ||
!strncmp(pchFile, "/dev/", 5))
{
bFile = FALSE;
strcpy(ptf->achFile, pchFile + 5);
iDevice = SendMessage(hwndManager, TKWM_GETDEVNO, 0, (LPARAM) ptf);
pchFile += 5;
if ((c = strchr(pchFile, '/')) != 0)
pchFile = c + 1;
}
else
{
bFile = TRUE;
strcpy(ptf->achFile, "file");
iDevice = SendMessage(hwndManager, TKWM_GETDEVNO, 0, (LPARAM) ptf);
}
if (find_location(pt, &fd, &ifd) == -1)
return -1;
ptf->iDevice = iDevice;
ptf->iTask = (pt - _tasks);
if (bFile)
{
if (isalpha(pchFile[0]) && pchFile[1] == ':')
{
if (pchFile[2] == '\\')
{
strcpy(ptf->achFile, pchFile);
}
else
{
strncpy(ptf->achFile, pchFile, 2);
getcurdir(toupper(pchFile[0]), ptf->achFile + 2);
if (ptf->achFile[strlen(ptf->achFile) - 1] != '\\')
strcat(ptf->achFile, "\\");
strcat(ptf->achFile, pchFile + 2);
}
}
else
{
if (pchFile[0] == '\\')
{
getcwd(ptf->achFile, _FNLEN);
ptf->achFile[2] = '\0';
strcat(ptf->achFile, pchFile);
}
else
{
getcwd(ptf->achFile, _FNLEN);
if (ptf->achFile[strlen(ptf->achFile) - 1] != '\\')
strcat(ptf->achFile, "\\");
strcat(ptf->achFile, pchFile);
}
}
}
else
{
strcpy(ptf->achFile, pchFile);
}
ptf->nMode = nMode;
ptf->nAccess = nAccess;
id = SendMessage(hwndManager, TKWM_OPEN, 0, (LPARAM) ptf);
if (id == -1)
return -1;
_files[ifd].tf_cnt = 1;
_files[ifd].tf_id = id;
_files[ifd].tf_dev = iDevice;
pt->files[fd] = ifd;
return fd;
}
long far _export
tkern_seek( int fd,
long nPosition,
int nStart)
{
struct task *pt;
pt = GetTaskInfo();
if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
{
pt->nError = EBADF;
return -1;
}
ptf->iDevice = _files[pt->files[fd]].tf_dev;
ptf->iTask = (pt - _tasks);
ptf->nPosition = nPosition;
ptf->nFrom = nStart;
return SendMessage(hwndManager, TKWM_SEEK,
_files[pt->files[fd]].tf_id,
(LPARAM) ptf);
}
int far _export
tkern_read( int fd,
char *pchBuffer,
int nBytes)
{
struct task *pt;
LRESULT nRead;
int nTotal = 0;
int nNow;
pt = GetTaskInfo();
if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
{
pt->nError = EBADF;
return -1;
}
if (nBytes < 0)
{
pt->nError = EINVAL;
return -1;
}
if (_files[pt->files[fd]].tf_eof)
{
_files[pt->files[fd]].tf_eof = 0;
return 0;
}
while(1)
{
/*
* We set this structure up inside the loop because it is shared among
* tasks, and if we end up sleeping, another task may overwrite this
*/
nNow = nBytes;
if (nNow > _FBUFSZ)
nNow = _FBUFSZ;
ptf->iDevice = _files[pt->files[fd]].tf_dev;
ptf->iTask = (pt - _tasks);
ptf->nBytes = nNow;
nRead = SendMessage(hwndManager, TKWM_READ,
_files[pt->files[fd]].tf_id,
(LPARAM) ptf);
if (nRead == -1)
{
return -1;
}
if (nRead != FR_NOTREADY)
{
nTotal += (int) nRead;
nBytes -= (int) nRead;
memcpy(pchBuffer, ptf->achBuffer, (int) nRead);
pchBuffer += (int) nRead;
if (!nBytes || !nRead)
{
if (nTotal && !nRead)
_files[pt->files[fd]].tf_eof = 1;
return nTotal;
}
}
else if (nTotal)
{
return nTotal;
}
else
{
GetMessages(pt);
}
}
}
int far _export
tkern_write( int fd,
char const *pchBuffer,
int nBytes)
{
struct task *pt;
int nTotal = 0;
int nWritten;
int nNow;
pt = GetTaskInfo();
if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
{
pt->nError = EBADF;
return -1;
}
if (nBytes < 0)
{
pt->nError = EINVAL;
return -1;
}
while (nBytes)
{
nNow = nBytes;
if (nNow > _FBUFSZ)
nNow = _FBUFSZ;
ptf->iDevice = _files[pt->files[fd]].tf_dev;
ptf->iTask = (pt - _tasks);
memcpy(ptf->achBuffer, pchBuffer, nNow);
ptf->nBytes = nNow;
nWritten = (int) SendMessage(hwndManager, TKWM_WRITE,
_files[pt->files[fd]].tf_id,
(LPARAM) ptf);
if (nWritten == -1)
return -1;
if (nWritten != FR_NOTREADY)
{
nTotal += (int) nWritten;
nBytes -= (int) nWritten;
pchBuffer += (int) nWritten;
if (!nBytes || !nWritten)
return nTotal;
}
else
{
GetMessages(pt);
}
}
return nTotal;
}
int far _export
tkern_close( int fd)
{
struct task *pt;
int ifd;
pt = GetTaskInfo();
if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
{
pt->nError = EBADF;
return -1;
}
ifd = pt->files[fd];
pt->files[fd] = -1;
if (!--_files[ifd].tf_cnt)
{
_files[ifd].tf_eof = 0;
ptf->iTask = (pt - _tasks);
ptf->iDevice = _files[ifd].tf_dev;
return SendMessage(hwndManager, TKWM_CLOSE,
_files[ifd].tf_id,
(LPARAM) ptf);
}
else
return 0;
}
void
internal_close( int fd,
int iTask)
{
int ifd;
ifd = _tasks[iTask].files[fd];
_tasks[iTask].files[fd] = -1;
if (!--_files[ifd].tf_cnt)
{
ptf->iDevice = _files[ifd].tf_dev;
ptf->iTask = iTask;
SendMessage( hwndManager,
TKWM_CLOSE,
_files[ifd].tf_id,
(LPARAM) ptf);
}
}
int far _export
tkern_dup(int fd_in)
{
struct task *pt;
int fd;
pt = GetTaskInfo();
if (fd_in < 0 || fd_in >= UFILE_MAX || pt->files[fd_in] == -1)
{
pt->nError = EBADF;
return -1;
}
for (fd = 0; fd < UFILE_MAX; fd++)
{
if (pt->files[fd] == -1)
{
pt->files[fd] = pt->files[fd_in];
_files[pt->files[fd]].tf_cnt++;
return fd;
}
}
pt->nError = EMFILE;
return -1;
}
int far _export
tkern_dup2( int fd_in,
int fd)
{
struct task *pt;
pt = GetTaskInfo();
if (fd_in < 0 || fd_in >= UFILE_MAX ||
fd < 0 || fd >= UFILE_MAX || pt->files[fd_in] == -1)
{
pt->nError = EBADF;
return -1;
}
if (pt->files[fd] != -1)
internal_close(fd, pt - _tasks);
pt->files[fd] = pt->files[fd_in];
_files[pt->files[fd]].tf_cnt++;
return fd;
}
int far _export
tkern_pipe(int *pfd)
{
if ((pfd[0] = tkern_open("/dev/pipe/input", 0, 0)) == -1)
return -1;
if ((pfd[1] = tkern_open("/dev/pipe/output", 0, 0)) == -1)
{
tkern_close(pfd[0]);
return -1;
}
return 0;
}
int far _export
tkern_isatty(int fd)
{
struct task *pt;
pt = GetTaskInfo();
if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
{
pt->nError = EBADF;
return -1;
}
ptf->iTask = (pt - _tasks);
ptf->iDevice = _files[pt->files[fd]].tf_dev;
return SendMessage(hwndManager, TKWM_ISATTY,
_files[pt->files[fd]].tf_id,
(LPARAM) ptf);
}
int far _export
tkern_ioctl( int fd,
long nIOCtl,
char *pchBuffer)
{
int nSize = ((nIOCtl & TK_IOCTL_PARM_SIZE) >> 16);
int iReturn = 0;
int ifd;
struct task *pt;
pt = GetTaskInfo();
if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
{
pt->nError = EBADF;
return -1;
}
ifd = pt->files[fd];
if (nIOCtl & TK_IOCTL_READ_STRING)
{
strncpy(ptf->tki.achBuffer, pchBuffer, nSize - 1);
ptf->tki.achBuffer[nSize - 1] = 0;
}
else if (nIOCtl & TK_IOCTL_READ_INT)
{
memcpy(ptf->tki.achBuffer, pchBuffer, nSize);
}
ptf->iDevice = _files[ifd].tf_dev;
ptf->tki.nIOCtl = nIOCtl;
ptf->tki.nSize = nSize;
iReturn = SendMessage(hwndManager, TKWM_IOCTL, _files[ifd].tf_id, (LPARAM) ptf);
if (iReturn != -1)
{
nSize = ptf->tki.nSize;
if (nIOCtl & TK_IOCTL_WRITE_STRING)
{
strncpy(pchBuffer, ptf->tki.achBuffer, nSize - 1);
pchBuffer[nSize - 1] = 0;
}
else if (nIOCtl & TK_IOCTL_WRITE_INT)
{
memcpy(pchBuffer, ptf->tki.achBuffer, nSize);
}
}
return iReturn;
}
int far _export
tkern_is_device(int fd,
char const *pchDevice)
{
struct task *pt;
int ifd;
int iDevice;
pt = GetTaskInfo();
if (fd < 0 || fd >= UFILE_MAX || pt->files[fd] == -1)
{
pt->nError = EBADF;
return -1;
}
ifd = pt->files[fd];
strcpy(ptf->achFile, pchDevice);
iDevice = SendMessage(hwndManager, TKWM_GETDEVNO, 0, (LPARAM) ptf);
return (_files[ifd].tf_dev == iDevice);
}
void
files_init(void)
{
memset(_files, 0, sizeof(_files));
hTFMem = GlobalAlloc(GMEM_FIXED | GMEM_SHARE, sizeof(*ptf));
ptf = (struct tfunc *) GlobalLock(hTFMem);
}
void
files_cleanup(void)
{
GlobalUnlock(hTFMem);
GlobalFree(hTFMem);
}
int far _export
tkern_valid_file(int fd)
{
struct task *pt;
pt = GetTaskInfo();
return (pt->files[fd] != -1);
}